<template>
  <div 
    :class="[
      'bx-affix',
      {
        'bx-affix--fixed': isFixed
      }
    ]"
    :style="affixStyle"
  >
    <div 
      ref="contentRef"
      :style="contentStyle"
    >
      <slot></slot>
    </div>
  </div>
</template>

<script>
import { ref, computed, onMounted, onUnmounted } from 'vue'

export default {
  name: 'BxAffix',
  props: {
    offsetTop: {
      type: Number,
      default: 0
    },
    offsetBottom: {
      type: Number,
      default: undefined
    },
    target: {
      type: [String, Object],
      default: null
    },
    zIndex: {
      type: Number,
      default: 1000
    }
  },
  emits: ['change'],
  setup(props, { emit }) {
    const contentRef = ref(null)
    const isFixed = ref(false)
    const originalRect = ref({})
    const targetElement = ref(null)

    const affixStyle = computed(() => {
      if (!isFixed.value) return {}
      
      const style = {
        position: 'fixed',
        zIndex: props.zIndex
      }

      if (props.offsetTop !== undefined) {
        style.top = `${props.offsetTop}px`
      }
      
      if (props.offsetBottom !== undefined) {
        style.bottom = `${props.offsetBottom}px`
      }

      if (originalRect.value.width) {
        style.width = `${originalRect.value.width}px`
      }

      return style
    })

    const contentStyle = computed(() => {
      if (!isFixed.value) return {}
      
      return {
        width: originalRect.value.width ? `${originalRect.value.width}px` : 'auto'
      }
    })

    const getTargetRect = () => {
      if (targetElement.value) {
        return targetElement.value.getBoundingClientRect()
      }
      return {
        top: 0,
        bottom: window.innerHeight
      }
    }

    const updatePosition = () => {
      if (!contentRef.value) return

      const contentRect = contentRef.value.getBoundingClientRect()
      const targetRect = getTargetRect()

      // 保存原始尺寸
      if (!isFixed.value) {
        originalRect.value = {
          width: contentRect.width,
          height: contentRect.height,
          top: contentRect.top,
          left: contentRect.left
        }
      }

      let shouldFix = false

      if (props.offsetTop !== undefined) {
        // 顶部固定
        shouldFix = contentRect.top <= props.offsetTop
      } else if (props.offsetBottom !== undefined) {
        // 底部固定
        shouldFix = contentRect.bottom >= (targetRect.bottom - props.offsetBottom)
      }

      if (shouldFix !== isFixed.value) {
        isFixed.value = shouldFix
        emit('change', shouldFix)
      }
    }

    const handleScroll = () => {
      updatePosition()
    }

    const handleResize = () => {
      if (!isFixed.value) {
        updatePosition()
      }
    }

    onMounted(() => {
      // 确定目标元素
      if (props.target) {
        if (typeof props.target === 'string') {
          targetElement.value = document.querySelector(props.target)
        } else {
          targetElement.value = props.target
        }
      }

      // 添加事件监听
      const scrollTarget = targetElement.value || window
      scrollTarget.addEventListener('scroll', handleScroll, { passive: true })
      window.addEventListener('resize', handleResize, { passive: true })

      // 初始检查
      updatePosition()
    })

    onUnmounted(() => {
      const scrollTarget = targetElement.value || window
      scrollTarget.removeEventListener('scroll', handleScroll)
      window.removeEventListener('resize', handleResize)
    })

    return {
      contentRef,
      isFixed,
      affixStyle,
      contentStyle
    }
  }
}
</script>

<style scoped>
.bx-affix {
  /* 基础样式 */
}

.bx-affix--fixed {
  /* 固定状态样式 */
}
</style>

